package commons.base.http.client;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

public class HttpClientFactory {

	public CloseableHttpClient createHttpClient(){
		CloseableHttpClient httpclient = HttpClientBuilder.create()
				.setDefaultRequestConfig(customRequestConfig())
				.setDefaultSocketConfig(customSocketConfig())
				.setConnectionManager(createHttpClientConnectionManager())
				.build();
		
		return httpclient;
	}
	
	protected RequestConfig customRequestConfig(){
		return  RequestConfig.custom()
				.setSocketTimeout(30000)
				.setConnectTimeout(30000)
				.build();
	}
	
	protected SocketConfig customSocketConfig(){
		return SocketConfig.custom()
				.setSoReuseAddress(true)
				.setTcpNoDelay(true)
				.build();
	}
	
	protected HttpClientConnectionManager createHttpClientConnectionManager(){
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(getDefaultRegistry());
		
		int maxConnections = 100;
		connManager.setDefaultMaxPerRoute(maxConnections);
		connManager.setMaxTotal(2 * maxConnections);
		
		return connManager;
	}
	
	protected Registry<ConnectionSocketFactory> getDefaultRegistry() {
        return RegistryBuilder.<ConnectionSocketFactory>create()
        		.register("http", createSocketFactory())
                .register("https", createSSLSocketFactory())
                .build();
    }
	
	protected ConnectionSocketFactory createSocketFactory(){
		return PlainConnectionSocketFactory.getSocketFactory();
	}
	
	// 忽略https证书验证
	protected ConnectionSocketFactory createSSLSocketFactory() {
		try {
			SSLContext ctx = SSLContext.getInstance("TLS");
			
			X509TrustManager tm = new X509TrustManager() {
				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					return null;
				}
				public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}
				public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				}
			};
			
			ctx.init(null, new TrustManager[] { tm }, null);
			
			HostnameVerifier allowAllVerifier = new HostnameVerifier(){
				@Override
				public boolean verify(String hostname, SSLSession session) {
					return true;
				}
			};
			
			return new SSLConnectionSocketFactory(ctx, allowAllVerifier);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return SSLConnectionSocketFactory.getSocketFactory();
	}
}
